package Code.Day11_20241012.com.dx.day11;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.RandomAccessFile;

/**
 * 文件基本操作
 */
public abstract class FileUtil {

	/**************************** 操作目录 <文件夹> *********************************/
	/**
	 * 创建目录
	 * @param name 传进一个目录名称
	 */
	public static void newFolder(String name) throws Exception {
		// 定位并创建文件夹
		File file = new File(name);
		// file.mkdir(); //只能创建一层目录
		file.mkdirs(); // 创建多层目录（包括不存在的目录）
	}

	/**
	 * 删除文件夹(文件夹中可以有内容)
	 * @param folderPath 文件夹完整绝对路径
	 */
	public static void delFolder(String folderPath) {
		try {
			delAllFile(folderPath); // 删除完里面所有内容
			String filePath = folderPath;
			filePath = filePath.toString();
			File myFilePath = new File(filePath);
			myFilePath.delete(); // 删除空文件夹
		} catch (Exception e) {
			System.out.println("删除文件夹操作出错");
		}
	}

	/********************************* 操作文件 ******************************************/

	/**
	 * 创建文件
	 * @param path 指定文件路径
	 */
	public static void createFile(String path) {
		try {
			File f = new File(path);
			if (f.exists()) { // 判断文件是否存在：
				System.out.println("文件已存在！");
				return;
			} else {
				// f.createNewFile(); // 创建文件：(只能创建文件，文件夹必须提前存在)
				// 创建文件，包括没有的文件夹
				  File fileParent = f.getParentFile();
				  if(!fileParent.exists()){ 
					  fileParent.mkdirs();
				  }
				  f.createNewFile();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 删除单个文件
	 * @param fileName 被删除文件的文件名
	 * @return 单个文件删除成功返回true,否则返回false
	 */
	public static boolean deleteFile(String fileName) {
		File file = new File(fileName);
		if (file.isFile() && file.exists()) {
			file.delete();
			System.out.println("删除单个文件" + fileName + "成功！");
			return true;
		} else {
			System.out.println("删除单个文件" + fileName + "失败！");
			return false;
		}
	}

	/**
	 * 获取文件详情
	 * @param path
	 */
	public static void getFileDetail(String path) {
		try {
			System.out.println("-------------文件信息-------------");
			File f = new File(path);
			System.out.println("文件全路径名: " + f);
			System.out.println("文件名: " + f.getName());
			System.out.println("文件所在路径: " + f.getPath());
			System.out.println("文件是否存在: " + f.exists());
			System.out.println("是否可读: " + f.canRead());
			System.out.println("是否可写: " + f.canWrite());
			System.out.println("是否可执行: " + f.canExecute());
			System.out.println("文件长度: " + f.length());
			System.out.println("是否为文件: " + f.isFile());
			System.out.println("是否为目录: " + f.isDirectory());
			System.out.println("文件绝对路径: " + f.getAbsolutePath());
			System.out.println("文件标准路径: " + f.getCanonicalPath());
			System.out.println("是否是隐藏文件: " + f.isHidden());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 递归：查看某目录下文件列表
	 * @param path
	 */
	public static void recursionShowFileList(String path) {
		File dir = new File(path);
		File[] files = dir.listFiles();
		if (files == null) {
			return;
		}
		for (int i = 0; i < files.length; i++) {
			// 如果是目录
			if (files[i].isDirectory()) {
				// 递归调用
				recursionShowFileList(files[i].getAbsolutePath());
			} else {
				System.out.println("======>" + files[i].getAbsolutePath());
			}
		}
	}

	
	
	/************************ 对文件内容的操作 ***********************************/
	/**
	 * 缓冲字符流-实现文件读取 不能读取二进制文件
	 * 读文件到内存中
	 */
	public static void readByBufferedReader(String filePath) throws Exception {
		BufferedReader br = new BufferedReader(new FileReader(filePath));
		String temp = "";
		while ((temp = br.readLine()) != null) {
			System.out.println(temp);
		}
		br.close();
	}


	/**
	 * 缓冲字符流-写入文件
	 */
	public static void writeByBufferedWriter(String filePath, String content)
			throws Exception {
		// 追加内容：把第二个参数设为true
		BufferedWriter bw = new BufferedWriter(new FileWriter(filePath, true));
		bw.write(content);
		bw.flush();
		bw.close();
	}


	/**
	 * 不能拷贝目录（只能拷贝文件）
	 * 缓冲字节流-实现文件拷贝 支持二进制拷贝
	 * @param sourceFile 准备复制的文件源
	 * @param targetFile 拷贝到新路径的文件
	 * ("d://LogController.java", "d://abc/LogController.java") //拷贝到的目录，也需要指定文件名
	 */
	public static void copyFileByBufferedInputStream(String sourceFile,
			String targetFile) throws Exception {
		// 输入流
		BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
				sourceFile));
		// 输出流
		BufferedOutputStream bos = new BufferedOutputStream(
				new FileOutputStream(targetFile));
		int c = 0;
		while ((c = bis.read()) != -1) {
			// 写入文件
			bos.write(c);
		}
		bis.close();
		bos.flush();
		bos.close();
	}

	
	/**
	 * 移动文件<源文件丢失>不能移动文件夹 
	 * @param oldPath
	 * @param newPath
	 * @return            //移动到的目录，也需要指定文件名
	 * ("d://LogController.java", "d://eee/LogController.java")
	 */
	public static void moveFile(String oldPath, String newPath)
			throws Exception {
		copyFileByInputStream(oldPath, newPath);
		deleteFile(oldPath);
	}
	
	
	/**
	 * 复制整个文件夹的内容
	 * @param oldPath 准备拷贝的目录
	 * @param newPath 指定绝对路径的新目录
	 * ("d://VMware10", "c://VMware10")
	 */
	public static void copyFolder(String oldPath, String newPath) {
		try {
			new File(newPath).mkdirs(); // 如果文件夹不存在 则建立新文件夹
			File a = new File(oldPath);
			String[] file = a.list();
			File temp = null;
			for (int i = 0; i < file.length; i++) {
				if (oldPath.endsWith(File.separator)) {
					temp = new File(oldPath + file[i]);
				} else {
					temp = new File(oldPath + File.separator + file[i]);
				}
				if (temp.isFile()) {
					FileInputStream input = new FileInputStream(temp);
					FileOutputStream output = new FileOutputStream(newPath
							+ "/" + (temp.getName()).toString());
					byte[] b = new byte[1024 * 5];
					int len;
					while ((len = input.read(b)) != -1) {
						output.write(b, 0, len);
					}
					output.flush();
					output.close();
					input.close();
				}
				if (temp.isDirectory()) {// 如果是子文件夹
					copyFolder(oldPath + "/" + file[i], newPath + "/" + file[i]);
				}
			}
		} catch (Exception e) {
			System.out.println("复制整个文件夹内容操作出错");
		}
	}

	
	/**
	 * 移动目录
	 * @param oldPath
	 * @param newPath
	 */
	public static void moveFolder(String oldPath, String newPath) {
		copyFolder(oldPath, newPath);
		delFolder(oldPath);
	}


	/**
	 * 二进制文件拷贝
	 */
	public static void copyBinaryFile(String sourceFile, String targetFile)
			throws Exception {
		DataInputStream dis = null; // 输入流(读)
		DataOutputStream dos = null;// 输出流(写)
		// 创建输入流
		dis = new DataInputStream(new FileInputStream(sourceFile));
		// 创建输出流
		dos = new DataOutputStream(new FileOutputStream(targetFile));
		int k;
		// 读、写
		while ((k = dis.read()) != -1) {

			dos.write(k);
		}
		// 释放资源
		dis.close();
		dos.flush();
		dos.close();
	}

	

	
	
	
	
	







	/******************** 其他方法 ***************************************/

	/**
	 * 字符流-实现文件读取
	 */
	public static void readByFileReader(String filePath) throws Exception {

		char[] c = new char[10]; // 声明一个存放内容的字符数组
		FileReader fr = new FileReader(filePath); // 构造FileReader对象
		int num = fr.read(c); // 执行读的操作
		String content = new String(c);
		System.out.println("文件内容: " + content);
		System.out.println("字符总数: " + num);
		fr.close();// 关闭

	}

	/**
	 * 字符流-写入文件
	 */
	public static void writeByFileWriter(String filePath, String content)
			throws Exception {
		FileWriter fw = new FileWriter(filePath);
		fw.write(content);
		fw.close();
		System.out.println("内容已写入文件!");

	}

	/**
	 * 字符流-写入文件,支持转义字符
	 */
	public static void writeByFormat(String filePath) {
		try {
			FileWriter fw = new FileWriter(filePath);
			String content = "HELLO,\r\n ACCP!";
			fw.write(content);
			fw.close();
			System.out.println("内容已写入文件!");
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * RandomAccessFile-写入文件(操作相对复杂，不建议使用)
	 * 
	 * @param fileName
	 *            文件名
	 * @param content 追加的内容
	 */
	public static void writeByRandomAccessFile(String fileName, String content) {
		try {
			// 打开一个随机访问文件流，按读写方式
			RandomAccessFile randomFile = new RandomAccessFile(fileName, "rw");
			// 文件长度，字节数
			long fileLength = randomFile.length();
			// 将文件指针移到文件末尾
			randomFile.seek(fileLength);
			randomFile.writeBytes(content);
			randomFile.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 字符流-实现文件拷贝
	 * @param sourceFile
	 *            源文件
	 * @param targetFile
	 *            目标文件
	 */
	public static void copyFileByCharacterStream(String sourceFile,
			String targetFile) throws Exception {
		BufferedReader br = null;
		BufferedWriter bw = null;
		try {
			// 缓冲指定文件的输入
			br = new BufferedReader(new FileReader(sourceFile));
			// 缓冲指定文件的输出
			bw = new BufferedWriter(new FileWriter(targetFile));
			while (br.ready()) {
				// 读取每一行并写入文件
				bw.write(br.readLine());
				bw.newLine();
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			// 刷新输出流缓冲，（输入流不需要刷新）
			bw.flush();
			bw.close();
			br.close();

		}
	}

	/**
	 * FileWriter-创建文件
	 * 
	 * @param filePath 文件路径
	 */
	public static void newFile(String filePath) throws Exception {
		// 创建FileWriter对象，用来写入字符流
		FileWriter fw = new FileWriter(filePath);
		fw.close();
	}

	/**
	 * 删除指定文件夹下所有文件
	 * 
	 * @param path 文件夹完整绝对路径
	 */
	public static boolean delAllFile(String path) {
		boolean bea = false;
		File file = new File(path);
		if (!file.exists()) {
			return bea;
		}
		if (!file.isDirectory()) {
			return bea;
		}
		String[] tempList = file.list();
		File temp = null;
		for (int i = 0; i < tempList.length; i++) {
			if (path.endsWith(File.separator)) {
				temp = new File(path + tempList[i]);
			} else {
				temp = new File(path + File.separator + tempList[i]);
			}
			if (temp.isFile()) {
				temp.delete();
			}
			if (temp.isDirectory()) {
				delAllFile(path + "/" + tempList[i]);// 先删除文件夹里面的文件
				delFolder(path + "/" + tempList[i]);// 再删除空文件夹
				bea = true;
			}
		}
		return bea;
	}

	/**
	 * 删除文件，可以是单个文件或文件夹
	 * 
	 * @param fileName 待删除的文件名
	 * @return 文件删除成功返回true,否则返回false
	 */
	public static boolean delete(String fileName) {
		File file = new File(fileName);
		if (!file.exists()) {
			System.out.println("删除文件失败：" + fileName + "文件不存在");
			return false;
		} else {
			if (file.isFile()) {
				return deleteFile(fileName);
			} else {
				return deleteDirectory(fileName);
			}
		}
	}

	/**
	 * 该方法借助系统命令实现文件删除
	 * 
	 * @param file
	 *            要删除文件的绝对路径
	 * @return boolean
	 * @throws Exception
	 */
	public static boolean deleteFileBySystemCommand(String file)
			throws Exception {
		if (file.equals("") || file == null) {
			throw new NullPointerException("信息不全,无法删除文件");
		} else {
			String command = "c:\\windows\\system32\\cmd.exe /C  del " + file;
			Runtime rt = Runtime.getRuntime();
			try {
				rt.exec(command);
				return true;
			} catch (Exception e) {
				throw new Exception("删除文件失败");
			}
		}
	}

	/**
	 * 删除目录（文件夹）以及目录下的文件
	 * 
	 * @param dir 被删除目录的文件路径
	 * @return 目录删除成功返回true,否则返回false
	 */
	public static boolean deleteDirectory(String dir) {
		// 如果dir不以文件分隔符结尾，自动添加文件分隔符
		if (!dir.endsWith(File.separator)) {
			dir = dir + File.separator;
		}
		File dirFile = new File(dir);
		// 如果dir对应的文件不存在，或者不是一个目录，则退出
		if (!dirFile.exists() || !dirFile.isDirectory()) {
			System.out.println("删除目录失败" + dir + "目录不存在！");
			return false;
		}
		boolean flag = true;
		// 删除文件夹下的所有文件(包括子目录)
		File[] files = dirFile.listFiles();
		for (int i = 0; i < files.length; i++) {
			if (files[i].isFile()) {// 删除子文件
				flag = deleteFile(files[i].getAbsolutePath());
				if (!flag) {
					break;
				}
			} else {// 删除子目录
				flag = deleteDirectory(files[i].getAbsolutePath());
				if (!flag) {
					break;
				}
			}
		}
		if (!flag) {
			System.out.println("删除目录失败");
			return false;
		}
		// 删除当前目录
		if (dirFile.delete()) {
			System.out.println("删除目录" + dir + "成功！");
			return true;
		} else {
			System.out.println("删除目录" + dir + "失败！");
			return false;
		}
	}



	/**
	 * 字节流-实现文件拷贝
	 * 
	 * @param sourceFile 准备复制的文件源
	 * @param targetFile 拷贝到新路径的文件
	 */
	public static void copyFileByInputStream(String sourceFile,
			String targetFile) throws Exception {
		FileInputStream in = null; // 输入流
		FileOutputStream out = null; // 输出流
		File source = new File(sourceFile);
		if (source.exists()) {
			in = new FileInputStream(sourceFile); // 用源文件路径-构建输入流
			out = new FileOutputStream(targetFile);// 用目标文件路径-构建输出流
			byte[] buffer = new byte[1024]; // 指定缓冲大小
			int length = 0;
			while ((length = in.read(buffer)) != -1) {
				// 写入文件
				out.write(buffer, 0, length);
			}
		}
		in.close();
		out.flush();
		out.close();
	}

}
